#define MAX_POS_INDICE 65535
#include "Indice.h"
#include <iostream>
using namespace std;

Indice::Indice() {
	for (int i = 0; i < MAX_POS_INDICE+1; i++) {
		indice[i] = MAX_POS_INDICE;
	}
}

Indice::~Indice() {
	//cout << "destructor Indice"<< endl;
}
 
Compresion* Indice::generarCompresion(Compresion *compr, BloqueTextoEntrada &bloque) {
	//cout << "compr->getPosicionCaracterActual() " <<compr->getPosicionCaracterActual()<<endl << " >= bloque.getCantCaracteresValidos() - 1 " << bloque.getCantCaracteresValidos() - 1<<endl;

	int tope;
	if (bloque.leyomenos()) tope = bloque.getSizeActual();
	else tope = bloque.getSizeActual()-1;

	//cout << "tope: " <<tope << endl;
	if (compr->getPosicionCaracterActual() >= tope)
	{
		/*if(bloque.getCantCaracteresValidos() == bloque.getSizeActual() && !bloque.leyomenos())
			bloque.setFinBloque(true);
		else
		{
			bloque.setFinArch(true);
			bloque.setFinBloque(true);
		}
		return compr;
	}*/

		//cout << "entro" << endl;
		//cout << compr->getPosicionCaracterActual()<< endl;

							//system("pause");
				bloque.setFinBloque(true);
				cout << "fin de bloque1" << endl;

				if (bloque.leyomenos()){

					//system("pause");
					cout << "fin de archivo1" << endl;

					bloque.setFinArch(true);
				}
				cout << "return compr;" << endl;

		return compr;

	}
	if (indice[compr->getContexto()] == MAX_POS_INDICE) {
		indice[compr->getContexto()] = compr->getPosicionCaracterActual();
	}
	int posCaracterActual = compr->getPosicionCaracterActual();
	int posCaracterPrediccion = indice[compr->getContexto()];
	char caracterPrediccion = bloque.getCaracterEnPos(posCaracterPrediccion);
	char caracterActual = bloque.getCaracterEnPos(posCaracterActual);

	int match = 0;
	while( caracterActual == caracterPrediccion && ((match + posCaracterPrediccion) < posCaracterActual) && match<255)
	{
		match ++;
		caracterActual = bloque.getCaracterEnPos(posCaracterActual + match);
		caracterPrediccion = bloque.getCaracterEnPos(posCaracterPrediccion + match);

		if (posCaracterActual + match >= bloque.getSizeActual()-1)
		{
			//si al avanzar la busqueda de match, no hay mas caracteres validos, seteo el estado del bloque segun corresponda

			bloque.setFinBloque(true);
			cout << "fin de bloque2" << endl;
			//system("pause");

			if(bloque.leyomenos()){
				//system("pause");
				cout << "fin de archivo2" << endl;
				bloque.setFinArch(true);

			}

			caracterActual = bloque.getCaracterEnPos(posCaracterActual);
			compr->setLongitud(match);
			return compr;
		}

	}
	caracterActual = bloque.getCaracterEnPos(posCaracterActual);
	compr->setLongitud(match);
	return compr;
}

Compresion* Indice::generarDescompresion(Compresion *compr, BloqueTextoSalida &bloque) {

	int longitudMatch = compr->getLongitud();
	if (longitudMatch == 0 && indice[compr->getContexto()] == MAX_POS_INDICE) {
		indice[compr->getContexto()] = compr->getPosicionCaracterActual();
		bloque.setCaracterEnPos(compr->getCaracter(), compr->getPosicionCaracterActual());
		if (compr->getPosicionCaracterActual() == bloque.getSize()-1)
			bloque.setFinBloque(true);
		return compr;
	}
	int posCaracterActual = compr->getPosicionCaracterActual();
	int posCaracterPrediccion = indice[compr->getContexto()];
	char caracterActual = compr->getCaracter();
	int aux = 0;
	while (aux < longitudMatch)	{
		bloque.setCaracterEnPos(bloque.getCaracterEnPos(posCaracterPrediccion+aux), posCaracterActual+aux);
		aux++;
	}
	bloque.setCaracterEnPos(caracterActual, posCaracterActual+longitudMatch);
	if (posCaracterActual+longitudMatch >= bloque.getSize()-1)
		bloque.setFinBloque(true);
	return compr;

}
